const { partial, initial, lowerFirst } = require('lodash');
const { errCode, SUCCESS } = require('../tools/constants');
const { delQuotation, toLog } = require('./common/common');

//AvenirSQL的SQL解析模块
const parse = require('node-sqlparser').parse;
class SQL {
    constructor() {

    }

    parseSql(sql) {
        try {
            const res = parse(sql);
            toLog("sql parse -> ", res);
            return res;
        } catch (e) {
            toLog("sql parse error - >", e);
            log.error('error sql :',sql);
            throw ('SQL_PARSE_ERROR');
        }
    }

    //解析AvenirSQL
    async parseAvenirSql(array, rawSql, sign) {
        const jump = () => {
            throw ('error');        //这个函数不是真正的error，只是要告诉外层函数去转交给sqlParser处理
        }
        const fail = () => {
            log.error("error sql :",rawSql);
            throw ('SQL_PARSE_ERROR');
        }
        if (array.length > ini.db.maxSqlLength) {
            throw ('SQL_TOO_LONG');
        }
        let parseRes = {};
        switch (array[0]) {
            case 'use':
                //解析use xxx命令
                if (array.length != 2) {
                    jump();
                } else {
                     await db.useDB(array[1]);
                }
                break;
            case 'create':
                //解析create database 命令
                if (array[1] === 'database') {
                    let res = await db.createDb(array[2]);
                    return res;
                } else if (array[1] === 'user') {
                    //解析create user 命令 create user name password auth  用户名 密码
                    if(array.length != 4 && array.length != 5) {
                        fail();
                    } else {
                        let name = array[2];
                        let password = array[3];
                        let auth = array[4];
                        //在这里先判断用户名和密码是否正确？
                        if(conn.isRoot(sign)) {
                            await user.createUser(name,password,auth,sign);
                        } else {
                            throw ('PERMISSION_DENIED');
                        }
                        
                        
                    }
                } else {
                    jump();
                }

                break;
            case 'drop':
                //drop database
                if (array.length !== 3) {
                    toLog("array.length = ", array.length);
                    throw ('SQL_PARSE_ERROR');
                }
                if (array[1] == 'database') {
                    await db.dropDatabase(array[2]);
                } else if (array[1] == 'table') {
                    await db.dropTable(array[2], sign);
                } else {
                    fail();
                }
                break;
            case 'show':
                //20201229 show database,show table
                if(array.length != 2 && array.length != 3) {
                    throw ('SQL_PARSE_ERROR');
                }
                if(array[1] === 'database') {
                    await db.showDatabase();
                } else if (array[1] === 'table') {
                    await db.showTable(array[2]);
                } else {
                    throw ('SQL_PARSE_ERROR');
                }
                break;
            default:
                //随便throw一个东西就行了
                jump();
        }
    }


    //包含原生SQL和能够被AvenirSQL识别的语句
    async parse(sql, sign) {
        //先解析AvenirSQL特有的语句 再解析原生SQL
        toLog("要解析的 sql为 ", sql);
        let raw = this.getArray(sql);
        if (raw.length === 0 || !sql) {
            throw ('SQL_PARSE_ERROR');
        } else {
            //AvenirSQL解析出错不报错，转给解析器解析，解析器报错直接throw
            try {
                await this.parseAvenirSql(raw, sql, sign);
            } catch (error) {
                //不是内部定义的错误就代表程序处理出错了
                toLog('error = ', error);
                if (error == SUCCESS || error != 'error') {
                    throw (error);
                }

                //不需要try catch了，底层会抓住错误
                let par = this.parseSql(sql);
                await this.doSql(par, sign);

            }
        }
    }

    getArray(sql) {
        if (!sql) {
            throw ('INVALID_SQL_ERROR');
        }
        let res = sql.split(' ');
        return res;
    }

    //根据解析出来的sql进行一系列操作
    async doSql(par, sign,auth) {
        if (par.type == 'create_table') {
            await db.createTable(par, sign,auth);
        } else if (par.type === 'insert') {
            await db.insert(par, sign,auth);
        } else if (par.type === 'delete') {
            await db.delete(par, sign,auth);
        } else if (par.type === 'select') {
            await db.select(par, sign,auth);
        } else if (par.type === 'update') {
            await db.update(par, sign,auth);
        }
    }


}
module.exports = SQL;